package vn.vfriends.mcms.site.filter;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import javax.inject.Inject;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.net.ftp.FTPFile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import vn.vfriends.mcms.site.model.Site;
import vn.vfriends.mcms.site.service.FTPFileService;
import vn.vfriends.mcms.site.service.SiteService;

/**
 *
 * @author tuan@vfriends.vn
 */
@WebFilter(filterName="ContentFilter")
public class ContentFilter implements Filter {

    private static final Logger logger = LoggerFactory.getLogger(ContentFilter.class);
    
    private static String LOCAL_PATH;
    
    private static boolean USING_FTP;
    
    @Inject private SiteService siteService;
    
    @Inject private FTPFileService ftpFileService;
    
    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        ServletContext servletContext = filterConfig.getServletContext();
        LOCAL_PATH = servletContext.getInitParameter("LOCAL_PATH");
        USING_FTP = Boolean.valueOf(servletContext.getInitParameter("USING_FTP"));
    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest hreq = (HttpServletRequest) request;
        HttpServletResponse resp = (HttpServletResponse) response;
        String siteName = request.getParameter("site");
        if(siteName != null) {
            Site site = this.siteService.findSiteByName(siteName);
            if (site == null) {
                resp.sendRedirect(hreq.getContextPath() + "/sitenotexist.jsf");
                return;
            } else {
                String localPath = FilenameUtils.concat(LOCAL_PATH, site.getName());
                File siteFile = new File(localPath);
                if (!siteFile.exists() || siteFile.listFiles().length == 0) {
                    FileUtils.forceMkdir(siteFile);

                    // Write site
                    if (USING_FTP) {
                        try {
                            writeLocalSite(File.separator + site.getName());
                        } catch (Exception e) {
                            logger.error(e.getMessage(), e);
                            throw new ServletException(e);
                        }
                    }
                }
            }
        }
        
        chain.doFilter(request, response);
    }

    @Override
    public void destroy() {}
    
    private void writeLocalSite(String path) throws Exception {
        FTPFile[] ftpFiles = this.ftpFileService.listFiles(path);
        for (FTPFile ftpFile : ftpFiles) {
            this.writeFile(ftpFile, path);
        }
    }
    
    private void writeFile(FTPFile ftpFile, String path) throws Exception {
        File file = new File(FilenameUtils.concat(LOCAL_PATH + path, ftpFile.getName()));
        if (ftpFile.isFile()) {
            if (!file.exists()) {
                file.createNewFile();
            }
            OutputStream outStream = null;
            try {
                outStream = new FileOutputStream(file);
                this.ftpFileService.retrieveFile(FilenameUtils.concat(path, ftpFile.getName()), outStream);
            } catch (Exception e) {
                logger.error(e.getMessage(), e);
                throw e;
            } finally {
                IOUtils.closeQuietly(outStream);
            }
        } else {
            FileUtils.forceMkdir(file);
            FTPFile[] ftpFiles = this.ftpFileService.listFiles(FilenameUtils.concat(path, file.getName()));
            for (FTPFile childFile : ftpFiles) {
                this.writeFile(childFile, FilenameUtils.concat(path, file.getName()));
            }
        }
    }

}
